﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using CI.Models.Production;
using CI.Models.Production.Interfaces;

namespace CI.Models.Data
{
    public class XmlDataRepository<T> : IStaticDataRepository<T> where T : KeyedDynamicBase
    {
        private XDocument _dataDocument;
        private readonly List<T> _rawList = new List<T>();
        private readonly Dictionary<int, T> _keyedLookup = new Dictionary<int, T>();

        public XmlDataRepository(string filePath)
        {
            var filePathInfo = new FileInfo(filePath);

            if (!filePathInfo.Exists)
                throw new FileNotFoundException("Cannot find specified xml file", filePathInfo.FullName);

            _dataDocument = XDocument.Load(filePathInfo.FullName);
        }

        public XmlDataRepository(Stream dataStream)
        {
            _dataDocument = XDocument.Load(dataStream);
        }

        public IEnumerable<T> All
        {
            get { return _rawList; }
        }

        #region IStaticDataRepository<T> Members

        public T Get(int id)
        {
            if (_keyedLookup.ContainsKey(id))
                return _keyedLookup[id];
            return null;
        }

        public void Load()
        {
            var p = new RigidXmlObjectParser(_dataDocument);

            AddListTypesToParser(p);

            foreach (var o in p.GetObjects<T>()) AddToInnerStores(o);
        }

        public int Count()
        {
            return _rawList.Count();
        }

        private void AddToInnerStores(T item)
        {
            _rawList.Add(item);
            _keyedLookup.Add(item.Key, item);
        }

        public void AddListTypesToParser(RigidXmlObjectParser parser)
        {
            parser.AddListType(typeof (RAM));
            parser.AddListType(typeof (Material));
            parser.AddListType(typeof (PIN));
            parser.AddListType(typeof(Region));
            parser.AddListType(typeof(Constellation));
            parser.AddListType(typeof(SolarSystem));
            parser.AddListType(typeof(JumpFrom));
            parser.AddListType(typeof(JumpTo));
        }

        #endregion
    }
}